#include "basic.h"
#include "struct.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"


static sample_format_e transform_sample_format( enum SampleFormat sample_fmt );
static void show( entry_s *ety );
//==============================================================================LIB INTERFACE
int parser( entry_s *ety )
{
	AVFormatContext *fc = NULL;

	av_register_all();
	avformat_open_input( &fc, ety->name, NULL, NULL);
	av_find_stream_info( fc );
	av_dump_format( fc, 0, ety->file_name, 0 );
	
	ety->bit_rate = fc->bit_rate;
	ety->duration = fc->duration;
	ety->sample_rate = fc->streams[0]->codec->sample_rate;
	ety->channels = fc->streams[0]->codec->channels;
	ety->sample_format = transform_sample_format( fc->streams[0]->codec->sample_fmt );
	ety->channel_layout = fc->streams[0]->codec->channel_layout;

	AVDictionaryEntry *meta = NULL;
	meta = av_dict_get( fc->metadata, "title", NULL, AV_METADATA_MATCH_CASE);
	if( meta != NULL ){
		ety->title = (char *)malloc( strlen(meta->value)+1 );
		strcpy( ety->title, meta->value );
	}else ety->title = NULL;
	
	meta = NULL;
	meta = av_dict_get( fc->metadata, "artist", NULL, AV_METADATA_MATCH_CASE);
	if( meta != NULL ){
		ety->artist = (char *)malloc( strlen(meta->value)+1 );
		strcpy( ety->artist, meta->value );
	}else ety->artist = NULL;

	meta = NULL;
	meta = av_dict_get( fc->metadata, "album", NULL, AV_METADATA_MATCH_CASE);
	if( meta != NULL ){
		ety->album = (char *)malloc( strlen(meta->value)+1 );
		strcpy( ety->album, meta->value );
	}else ety->album = NULL;
	
	show( ety );
	
	av_close_input_file(fc);

	return 0;
}

int decoder( entry_s *ety )
{	
	AVFormatContext *fc = NULL;
	
	av_register_all();
	avformat_open_input( &fc, ety->name, NULL, NULL);
	av_find_stream_info(fc);
	av_dump_format(fc, 0, ety->name, 0);

	AVCodecContext  *cc = NULL;
	AVCodec			*c = NULL;

	cc = fc->streams[0]->codec;
	c = avcodec_find_decoder(cc->codec_id);
	if( c == NULL ) return -1;
	avcodec_open( cc, c );

	short *target;
	target = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);	

	void *targets = malloc( 50 * 1024 * 1024 );
	ety->music_buf = targets;
	ety->music_buf_size = 0;
	ety->music_buf_end = ety->music_buf;

	AVPacket pk;
	av_init_packet(&pk);

	int i = 0;
	int len = 0;
	int size = 0;

	while( av_read_frame( fc, &pk ) >= 0 ){

		size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
		len = avcodec_decode_audio3(cc, target, /*int *frame_size_ptr*/&size, &pk);
	
		printf( "\n%d  ...compressed_size: %d  ...decompressed_size: %d", i, len, size  );
		memcpy( targets, target, size );
		targets += size;
		ety->music_buf_size += size;
		ety->music_buf_end += size;
		i++;
		av_free_packet(&pk);
	}	

	free(target);
	avcodec_close(cc);
	av_close_input_file(fc);

	while( getchar() != '\n' );
	return 0;
}

//------------------------------------------------------------------------------
static sample_format_e transform_sample_format( enum SampleFormat sample_fmt )
{
	switch( sample_fmt ){
		case SAMPLE_FMT_NONE : return UNKNOWSF;
		case SAMPLE_FMT_U8   : return U8;
		case SAMPLE_FMT_S16  : return S16_LE;
		case SAMPLE_FMT_S32  : return S32_LE;
		case SAMPLE_FMT_FLT  : return FLOAT_LE;
		case SAMPLE_FMT_DBL  : return UNKNOWSF;
		case SAMPLE_FMT_NB   : return UNKNOWSF;
	}
	return UNKNOWSF;
}

static void show( entry_s *ety )
{
	printf( "\nFFMPEG->" );
	printf( "channels: %d", ety->channels );
	printf( "\n\tsample_rate: %d", ety->sample_rate );
	printf( "\n\tsample_format: %d", ety->sample_format );
	printf( "\n\tbit_rate: %ld", ety->bit_rate );
	printf( "\n\tduration: %ld", ety->duration );
	printf( "\n\ttitle: %s", ety->title );
	printf( "\n\tartist: %s", ety->artist );
	printf( "\n\talbum: %s", ety->album );

}